/*
 * Title:        CloudScheduler Toolkit
 * Description:  a Toolkit for Modeling and Simulation of Job Scheduling and Resource Provisioning in Cloud System
 * Licence:      GPL - http://www.gnu.org/copyleft/gpl.html
 * Author:       Fuhui Wu
 *
 * Copyright (c) 2013-2014, The National University of Defense Technology, China
 */

package org.nudt.jCloud.example.resourceStealing2;

import java.util.ArrayList;
import java.util.List;

import org.nudt.jCloud.evaluation.Evaluation;
import org.nudt.jCloud.infrastructure.HomegeneousCluster;
import org.nudt.jCloud.infrastructure.SlotType;
import org.nudt.jCloud.jobScheduler.AFCFSScheduler;
import org.nudt.jCloud.jobScheduler.JobScheduler;
import org.nudt.jCloud.resourceManager.GeneralReservationRM;
import org.nudt.jCloud.resourceManager.ResManager;
import org.nudt.jCloud.resourceScaler.ConstantScaler;
import org.nudt.jCloud.resourceScaler.ResourceScaler;
import org.nudt.jCloud.simulation.CloudSchedSIM;
import org.nudt.jCloud.simulation.SIMTag;
import org.nudt.jCloud.simulation.User;
import org.nudt.jCloud.simulation.UserBroker;
import org.nudt.jCloud.workload.BatchWLGen;
import org.nudt.jCloud.workload.Workload;
import org.nudt.jCloud.workload.WorkloadGenerator;

public class ResourceStealing {
	
	private static SlotType slotType;
	private static HomegeneousCluster homeCluster;
	private static ResManager resManager;
	private static ArrayList<UserBroker> userBrokerList;
	private static ArrayList<JobScheduler> jobSchedulerList;
	private static ArrayList<ResourceScaler> resScalerList;
	private static int frwkNum;
	private static ArrayList<User> userList;
	
	public static void init(){
		slotType = new SlotType(1, 1000, 250, 0);
		homeCluster = new HomegeneousCluster(30, 1000, 4, 4000, 1000, 200000);
		resManager = new HeuristicStealingRM("Heuristic_Stealing", homeCluster, 120);
		userBrokerList = new ArrayList<UserBroker>();
		userList = new ArrayList<User>();
		jobSchedulerList = new ArrayList<JobScheduler>();
		resScalerList = new ArrayList<ResourceScaler>();
		List<WorkloadGenerator> wlGenList = new ArrayList<WorkloadGenerator>();
		
		frwkNum = 4;
		for(int i=0; i<frwkNum; ++i){
			WorkloadGenerator wlGen = new BatchWLGen(1000, 50, 30, 0.5, 60+i*10, slotType);
			wlGenList.add(wlGen);
		}
		
		for(int i=0; i<frwkNum; ++i){
			UserBroker userBroker = new UserBroker("UserBroker"+i, SIMTag.RM_MODE_R);
			Workload wl = wlGenList.get(i).generate(0);
			User user = new User("user"+i, wl);
			userList.add(user);
			userBroker.addUser(user);
			userBrokerList.add(userBroker);
			JobScheduler jobScheduler = new AFCFSScheduler("AFCFS"+i);
			jobSchedulerList.add(jobScheduler);
			ResourceScaler resourceScaler = new StealingScaler(slotType);
			resScalerList.add(resourceScaler);
			userBroker.init(jobScheduler, resourceScaler);
		}
	}
	
	public static void reset(String simName){
		CloudSchedSIM.reset(simName);
		resManager.reset();
		homeCluster.reset();
		for(int i=0; i<frwkNum; ++i){
			userBrokerList.get(i).reset();
			userList.get(i).reset();
			userBrokerList.get(i).addUser(userList.get(i));
			jobSchedulerList.get(i).reset();
			resScalerList.get(i).reset();
			userBrokerList.get(i).init(jobSchedulerList.get(i), resScalerList.get(i));
		}
	}
	
	public static void start(){
		CloudSchedSIM.addRM(resManager);
		for(int i=0; i<frwkNum; ++i){
			CloudSchedSIM.addUserBroker(userBrokerList.get(i));
		}
		CloudSchedSIM.startSimulation();		
	}
	
	public static void main(String[] args) {
		init();
		CloudSchedSIM.init("Heuristic_Stealing");
		start();
		
		System.out.println("------------------------------------------------------");
		
		reset("Static_Reservation");
		resManager = new GeneralReservationRM("Static_Reservation", homeCluster);
		resScalerList.clear();
		for(int i=0; i<frwkNum; ++i){
			ResourceScaler resScaler = new ConstantScaler(slotType, 30);
			resScalerList.add(resScaler);
			userBrokerList.get(i).init(jobSchedulerList.get(i), resScalerList.get(i));
		}		
		start();
		
		System.out.println("------------------------------------------------------");
		
		reset("Heuristic_Preemption");
		resManager = new HeuristicPreemptionRM("Heuristic_Preemption", homeCluster, 120);
		resScalerList.clear();
		for(int i=0; i<frwkNum; ++i){
			ResourceScaler resScaler = new StealingScaler(slotType);
			resScalerList.add(resScaler);
			JobScheduler jobScheduler = new PreemptionJobScheduler("AFCFS");
			userBrokerList.get(i).init(jobScheduler, resScalerList.get(i));
		}		
		start();
						
		for(int i=0; i<frwkNum; ++i){
			Evaluation.avgWaitTime("Static_Reservation", userList.get(i).getUserName());	
			Evaluation.avgWeightedWaitTime("Static_Reservation", userList.get(i).getUserName());	
		}
		System.out.println();
		for(int i=0; i<frwkNum; ++i){
			Evaluation.avgWaitTime("Heuristic_Stealing", "user"+i);
			Evaluation.avgWeightedWaitTime("Heuristic_Stealing", "user"+i);
		}		
		System.out.println();
		for(int i=0; i<frwkNum; ++i){
			Evaluation.avgWaitTime("Heuristic_Preemption", userList.get(i).getUserName());	
			Evaluation.avgWeightedWaitTime("Heuristic_Preemption", userList.get(i).getUserName());	
		}
				
	}
	
	
	public ResManager getResManager() {
		return resManager;
	}

}
